/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.core.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * {@code @AliasFor}是一个注解，用于声明注解属性的别名。
 * 注解属性。
 *
 *
 * 使用场景：
 * 注释中明确的别名： 在一个单一的注释中，{@code @AliasFor}可以在一对属性上声明，以表明它们是彼此可互换的别名。
 * 表明它们是彼此可互换的别名。元注释中的属性的明确别名：如果{@code @AliasFor}的{@link #annotation}属性被设置为一个不同的的注释，
 * 那么{@link #attribute}就会被解释为一个属性的别名，而不是声明它的注释。
 * 被解释为元注解中的一个属性的别名（即，一个明确的元注解属性）。明确的元注解属性覆盖）。)
 * 这使得我们能够精细地控制哪些属性在一个注解中被覆盖层次结构。
 * 事实上，通过{@code @AliasFor}，我们甚至可以声明一个元注解的{@code value}属性的别名。
 * 注解中的隐含别名：如果一个或多个属性在注解中是一个注解中的一个或多个属性被声明为同一元注解的属性覆盖为同一个元注解属性（直接或过渡地）。
 * 这些属性将被视为一组<em>隐式</em>别名彼此的别名，其行为类似于注释中的显式别名。
 * 注释中的别名。
 *
 *
 * 使用要求：
 * 就像Java中的任何注解一样，仅仅是{@code @AliasFor}的存在，并不能执行别名语义。
 * 本身并不能强制执行别名语义。
 * 为了使别名语义得到必须通过{@link MergedAnnotations}来加载注解。
 *
 *
 * 实现要求
 * 注解中明确的别名:
 * 构成别名对的每个属性都应该被注释为{@code @AliasFor}，并且{@link #attribute}或{@link #value}必须引用该对中的<em>另一个</em>属性。
 * 自从Spring Framework5.2.1以来，技术上有可能只对一个别名对中的一个属性进行注释。
 * 然而，我们建议在一个别名对中同时注解两个属性。
 * 然而，我们建议在一个别名对中同时注释两个属性，以获得更好的文档，并与以前的Spring框架的版本。
 *
 *
 * 依赖的属性必须声明相同的返回类型。依赖的属性必须声明默认值。
 * 相邻的属性必须声明一个缺省值。
 * 相邻属性必须声明相同的默认值。
 * {@link #annotation}不应该被声明。
 *
 *
 * 元注解中属性的明确别名:
 *
 * 作为元注释中的属性的别名的属性必须用{@code @AliasFor}来注释，并且{@link #attribute}必须引用元注解中的属性。
 * 别名属性必须声明相同的返回类型。
 * {@link #annotation}必须引用元注解。
 * 被引用的元注解必须是<em>meta-present</em>上的声明{@code @AliasFor}的注释类。
 *
 * 注解中的隐性别名:

 * 属于一组隐含别名的每个属性必须被用{@code @AliasFor}来注解，
 * 并且{@link #attribute}必须参考同一元注释中的同一属性（直接或通过其他明确的元注释通过其他明确的元注解属性覆盖来过渡地引用在注释层次结构中）。)
 * 同类属性必须声明相同的返回类型。
 * 同类属性必须声明一个默认值。
 * 别名属性必须声明相同的默认值。
 * {@link #annotation}必须引用一个适当的元注释。
 * 被引用的元注解必须是<em>meta-present</em>上的
 * 声明了{@code @AliasFor}的注释类。
 *
 * 例子。注解中的明确别名
 * 在{@code @ContextConfiguration}中，{@code value}和{@code locations}是彼此的明确别名。
 *
 * <pre class="code"> public &#064;interface ContextConfiguration {
 *
 *    &#064;AliasFor("locations")
 *    String[] value() default {};
 *
 *    &#064;AliasFor("value")
 *    String[] locations() default {};
 *
 *    // ...
 * }</pre>
 *
 * <h3>Example: Explicit Alias for Attribute in Meta-annotation</h3>
 * <p>In {@code @XmlTestConfig}, {@code xmlFiles} is an explicit alias for
 * {@code locations} in {@code @ContextConfiguration}. In other words,
 * {@code xmlFiles} overrides the {@code locations} attribute in
 * {@code @ContextConfiguration}.
 *
 * <pre class="code"> &#064;ContextConfiguration
 * public &#064;interface XmlTestConfig {
 *
 *    &#064;AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
 *    String[] xmlFiles();
 * }</pre>
 *
 * <h3>Example: Implicit Aliases within an Annotation</h3>
 * <p>In {@code @MyTestConfig}, {@code value}, {@code groovyScripts}, and
 * {@code xmlFiles} are all explicit meta-annotation attribute overrides for
 * the {@code locations} attribute in {@code @ContextConfiguration}. These
 * three attributes are therefore also implicit aliases for each other.
 *
 * <pre class="code"> &#064;ContextConfiguration
 * public &#064;interface MyTestConfig {
 *
 *    &#064;AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
 *    String[] value() default {};
 *
 *    &#064;AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
 *    String[] groovyScripts() default {};
 *
 *    &#064;AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
 *    String[] xmlFiles() default {};
 * }</pre>
 *
 * <h3>Example: Transitive Implicit Aliases within an Annotation</h3>
 * <p>In {@code @GroovyOrXmlTestConfig}, {@code groovy} is an explicit
 * override for the {@code groovyScripts} attribute in {@code @MyTestConfig};
 * whereas, {@code xml} is an explicit override for the {@code locations}
 * attribute in {@code @ContextConfiguration}. Furthermore, {@code groovy}
 * and {@code xml} are transitive implicit aliases for each other, since they
 * both effectively override the {@code locations} attribute in
 * {@code @ContextConfiguration}.
 *
 * <pre class="code"> &#064;MyTestConfig
 * public &#064;interface GroovyOrXmlTestConfig {
 *
 *    &#064;AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts")
 *    String[] groovy() default {};
 *
 *    &#064;AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
 *    String[] xml() default {};
 * }</pre>
 *
 * <h3>Spring Annotations Supporting Attribute Aliases</h3>
 * <p>As of Spring Framework 4.2, several annotations within core Spring
 * have been updated to use {@code @AliasFor} to configure their internal
 * attribute aliases. Consult the Javadoc for individual annotations as well
 * as the reference manual for details.
 *
 * @author Sam Brannen
 * @since 4.2
 * @see MergedAnnotations
 * @see SynthesizedAnnotation
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {

	/**
	 * {@link #attribute}的别名。
	 * 当{@link #annotation}没有被声明时，可以代替{@link #attribute}使用。
	 * 未被声明&mdash;
	 * 例如。{@code @AliasFor("value")}而不是{@code @AliasFor(attributee = "value")}.
	 */
	@AliasFor("attribute")
	String value() default "";

	/**
	 * 这个属性是一个别名的属性名称。
	 * @see #value
	 */
	@AliasFor("value")
	String attribute() default "";

	/**
	 * 被别名的{@link #attribute}所声明的注释类型。
	 * 默认为{@link Annotation}，意味着被别名的属性是在与this属性相同的注释中声明。
	 */
	Class<? extends Annotation> annotation() default Annotation.class;

}
